package ing.gzq.service;

import ing.gzq.base.Result;
import ing.gzq.base.ResultCache;
import ing.gzq.dao.QuestionDao;
import ing.gzq.model.*;
import ing.gzq.model.vo.QuestionStudentVO;
import ing.gzq.model.vo.QuestionTeacherVO;
import ing.gzq.websocket.WebsocketSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static ing.gzq.base.ResultCache.getDataOk;
import static ing.gzq.base.ResultCache.getFailureDetail;
import static ing.gzq.base.ResultCache.getPermissionDeniedDetail;
import static ing.gzq.model.Message.DELETE_QUESTION;
import static ing.gzq.model.Message.PUBLISH_QUESTION;
import static ing.gzq.model.Message.SEND_ANSWER;
import static ing.gzq.service.AuthenticationService.getUserInSecurityContext;

@Service
public class QuestionService {

    @Autowired
    QuestionDao questionDao;

    @Autowired
    AuthenticationService authService;

    @Autowired
    WebsocketSupport websocketSupport;


    public Result uploadQuestion(Question question) {
        if(!authService.checkIfInCourse(question.getCourseId()))
            return getPermissionDeniedDetail("not in course");

        User user = getUserInSecurityContext();
        question.setTeacherId(user.getUsername());
        try{
            questionDao.insertQuestion(question);

            Message<Question> message = new Message<>(PUBLISH_QUESTION);
            message.setData(question);
            websocketSupport.sendMessageToAll(question.getCourseId(),message);

            Map<String,Long> map = new HashMap<>(1);
            map.put("id",question.getId());
            return getDataOk(map);
        }catch (Exception ex){
            ex.printStackTrace();
            return getFailureDetail(ex.getMessage());
        }
    }

    @Transactional
    public Result deleteQuestion(Long questionId) {
        Question question = questionDao.getQuestionById(questionId);
        if(question == null)
            return ResultCache.OK;
        if(!authService.checkIfInCourse(question.getCourseId()))
            return getPermissionDeniedDetail("not in course");
        try{

            questionDao.deleteQuestion(questionId);
            questionDao.deleteAnswer(questionId);

            Message<Long> message = new Message<>(DELETE_QUESTION);
            message.setData(questionId);
            websocketSupport.sendMessageToAll(question.getCourseId(),message);

            return ResultCache.OK;
        }catch (Exception ex){
            ex.printStackTrace();
            return getFailureDetail(ex.getMessage());
        }
    }

    public Result getQuestionByTeacher(Long courseId) {
        if(!authService.checkIfInCourse(courseId))
            return getPermissionDeniedDetail("not in course");

        User user = getUserInSecurityContext();
        List<QuestionTeacherVO> questions = questionDao.getQuestionByTeacher(courseId,user.getUsername());
        return getDataOk(questions);
    }

    public Result getQuestionByStudent(Long courseId) {
        if(!authService.checkIfInCourse(courseId))
            return getPermissionDeniedDetail("not in course");

        User user = getUserInSecurityContext();
        List<QuestionStudentVO> questions = questionDao.getQuestionByStudent(courseId,user.getUsername());
        return getDataOk(questions);
    }

    public Result uploadAnswer(Answer answer) {
        Question question = questionDao.getQuestionById(answer.getQuestionId());
        if (question == null) {
            return getFailureDetail("question is not exist");
        }
        if(!authService.checkIfInCourse(question.getCourseId()))
            return getPermissionDeniedDetail("not in course");
        User user = getUserInSecurityContext();
        answer.setStudentId(user.getUsername());
        try{
            if(checkAnswered(user.getUsername(),answer.getQuestionId()))
                return getFailureDetail("has answered");
            questionDao.uploadAnswer(answer);

            Message<Answer> message = new Message<>(SEND_ANSWER);
            message.setName(user.getUsername());
            message.setData(answer);
            websocketSupport.sendMessageToTeacher(question.getCourseId(),message);

            return ResultCache.OK;
        }catch (Exception ex){
            ex.printStackTrace();
            return getFailureDetail(ex.getMessage());
        }
    }

    private boolean checkAnswered(String studentId, Long questionId) {
        return questionDao.checkAnswered(studentId, questionId) > 0;
    }
}
